// Local Includes
#include "stdafx.h"
#include "MyContext.h"

// SDL Includes
#include <sdl.h>

// System Includes
#include <math.h>

// System-indepenant paths ( a lofty goal!)
#define ObtainPath( file ) \
{                           \
}

MyContext::MyContext()
: _texture(),
  _instrument(),
#ifndef __APPLE_CC__
  _glActiveTexture(NULL),
#endif
  _font()
{
}

MyContext::~MyContext()
{
}

bool 
MyContext::configure()
{
    bool res;
    
    // Load Screen Textures
#ifdef WIN32
    //res = _texture[WINDOW_BACKGROUND_TEX].loadImage(".\\tex\\wind_bg.tif"); 
    res = _texture[PLAYER_BACKGROUND_TEX].loadImage(".\\tex\\player_bg.tif");
    res = _texture[PLAYER_BACKGROUNDA_TEX].loadImage(".\\tex\\player_bga.tif");
    res = _texture[PLAYER_POINTER_TEX].loadImage(".\\tex\\player_pntr.tif");
    res = _texture[WINDOW_BUTTON_TEX].loadImage(".\\tex\\button.tif"); 
    res = _texture[WINDOW_WARNING_TEX].loadImage(".\\tex\\warning.tif"); 
    res = _texture[SPLASH_YOU_WIN].loadImage(".\\tex\\splash.youwin.tif");
    res = _texture[SPLASH_NEXT_PLAYER].loadImage(".\\tex\\splash.nextplayer.tif");
    res = _texture[GAME_NOTE_PLAYED].loadImage(".\\tex\\note-played.tif");
    res = _texture[GAME_NOTE_UNPLAYED].loadImage(".\\tex\\note-unplayed.tif");
#else
    //res = _texture[WINDOW_BACKGROUND_TEX].loadImage("../../tex/wind_bg.tif"); 
    res = _texture[PLAYER_BACKGROUND_TEX].loadImage("../../tex/player_bg.tif");
    res = _texture[PLAYER_BACKGROUNDA_TEX].loadImage("../../tex/player_bga.tif");
    res = _texture[PLAYER_POINTER_TEX].loadImage("../../tex/player_pntr.tif");
    res = _texture[WINDOW_BUTTON_TEX].loadImage("../../tex/button.tif"); 
    res = _texture[WINDOW_WARNING_TEX].loadImage("../../tex/warning.tif"); 
    res = _texture[SPLASH_YOU_WIN].loadImage("../../tex/splash.youwin.tif");
    res = _texture[SPLASH_NEXT_PLAYER].loadImage("../../tex/splash.nextplayer.tif");
    res = _texture[GAME_NOTE_PLAYED].loadImage("../../tex/note-played.tif");
    res = _texture[GAME_NOTE_UNPLAYED].loadImage("../../tex/note-unplayed.tif");
#endif    

    // Load in all the instrument textures
#ifdef WIN32
    res = _instrument[INST_BASE_BASSDRUM].loadImage(".\\tex\\base.35.bassdrum.tif");
    res = _instrument[INST_BASE_SNARE].loadImage(".\\tex\\base.38.snare.tif");
    res = _instrument[INST_BASE_HIHAT].loadImage(".\\tex\\base.42.hihat.tif");
    res = _instrument[INST_BASE_LOWTOM].loadImage(".\\tex\\base.45.lowtom.tif");
    res = _instrument[INST_BASE_HIGHMIDTOM].loadImage(".\\tex\\base.48.midtom.tif");
    res = _instrument[INST_BASE_CRASHCYMBAL].loadImage(".\\tex\\base.49.crashcymbal.tif");
#else
    res = _instrument[INST_BASE_BASSDRUM].loadImage("../../tex/base.35.bassdrum.tif");
    res = _instrument[INST_BASE_SNARE].loadImage("../../tex/base.38.snare.tif");
    res = _instrument[INST_BASE_HIHAT].loadImage("../../tex/base.42.hihat.tif");
    res = _instrument[INST_BASE_LOWTOM].loadImage("../../tex/base.45.lowtom.tif");
    res = _instrument[INST_BASE_HIGHMIDTOM].loadImage("../../tex/base.48.midtom.tif");
    res = _instrument[INST_BASE_CRASHCYMBAL].loadImage("../../tex/base.49.crashcymbal.tif");
#endif
    
    // Load in all 3D instrument Textures
#ifdef WIN32
    res &= _3dTex[INST_BASE_HIGHMIDTOM][INST_TOP].loadImage(".\\tex\\3d.48.highmidtom.top.tif");
    res &= _3dTex[INST_BASE_HIGHMIDTOM][INST_SIDE].loadImage(".\\tex\\3d.48.highmidtom.side.tif");
    res &= _3dTex[INST_BASE_BASSDRUM][INST_TOP].loadImage(".\\tex\\3d.35.bassdrum.top.tif");
    res &= _3dTex[INST_BASE_BASSDRUM][INST_SIDE].loadImage(".\\tex\\3d.35.bassdrum.side.tif");
    res &= _3dTex[INST_BASE_HIHAT][INST_TOP].loadImage(".\\tex\\3d.42.hihat.top.tif");
    res &= _3dTex[INST_BASE_LOWTOM][INST_TOP].loadImage(".\\tex\\3d.45.lowtom.top.tif");
    res &= _3dTex[INST_BASE_LOWTOM][INST_SIDE].loadImage(".\\tex\\3d.45.lowtom.side.tif");
    res &= _3dTex[INST_BASE_SNARE][INST_TOP].loadImage(".\\tex\\3d.38.snare.top.tif");
    res &= _3dTex[INST_BASE_SNARE][INST_SIDE].loadImage(".\\tex\\3d.38.snare.side.tif");
    res &= _3dTex[INST_BASE_CRASHCYMBAL][INST_TOP].loadImage(".\\tex\\3d.49.crashcymbal.top.tif");
#else
    res &= _3dTex[INST_BASE_HIGHMIDTOM][INST_TOP].loadImage("../../tex/3d.48.highmidtom.top.tif");
    res &= _3dTex[INST_BASE_HIGHMIDTOM][INST_SIDE].loadImage("../../tex/3d.48.highmidtom.side.tif");
    res &= _3dTex[INST_BASE_BASSDRUM][INST_TOP].loadImage("../../tex/3d.35.bassdrum.top.tif");
    res &= _3dTex[INST_BASE_BASSDRUM][INST_SIDE].loadImage("../../tex/3d.35.bassdrum.side.tif");
    res &= _3dTex[INST_BASE_HIHAT][INST_TOP].loadImage("../../tex/3d.42.hihat.top.tif");
    res &= _3dTex[INST_BASE_LOWTOM][INST_TOP].loadImage("../../tex/3d.45.lowtom.top.tif");
    res &= _3dTex[INST_BASE_LOWTOM][INST_SIDE].loadImage("../../tex/3d.45.lowtom.side.tif");
    res &= _3dTex[INST_BASE_SNARE][INST_TOP].loadImage("../../tex/3d.38.snare.top.tif");
    res &= _3dTex[INST_BASE_SNARE][INST_SIDE].loadImage("../../tex/3d.38.snare.side.tif");
    res &= _3dTex[INST_BASE_CRASHCYMBAL][INST_TOP].loadImage("../../tex/3d.49.crashcymbal.top.tif");
#endif

    
#ifndef __APPLE_CC__
    // Detected OpenGL Functionality
    _glActiveTexture = (PFNGLACTIVETEXTUREPROC)SDL_GL_GetProcAddress("glActiveTexture");
#endif
    float color[] = { 1.0f, 1.0f, 1.0f, 1.0f };
    _font.init("Courier New", color );

    return true;
}

bool 
MyContext::renderText( char* pStr, int x, int y ) const
{
    return _font.render( (MyContext*)this, pStr, x, y );
}


bool
MyContext::renderSplash( MyTexObj id, unsigned int uiTime, 
                         float fCentX, float fCentY, 
                         float fTexW, float fTexH, 
                         bool bClear ) const
{
    unsigned int uiEnd = uiTime+ SDL_GetTicks();
    
    for(unsigned int ui = SDL_GetTicks(); ui < uiEnd; 
                     ui = SDL_GetTicks() ) {
                     
        if(bClear) {
            glClearColor( 0.0, 0.0, 0.0, 1.0 );
            glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        }
        
        MyImage * pImage = (MyImage*)texture(id);

        pImage->bindTexture();
        pImage->enableTexture();

        glColor4f( 1.0f, 0.0f, 0.0f, 1.0f );

        glBegin(GL_TRIANGLE_STRIP);  
            // Vertex 0
            glTexCoord2f(0.0f,0.0f);
            glVertex3f(fCentX-fTexW/2.0f,fCentY-fTexH/2.0f,0.0f);
            // Vertex 1
            glTexCoord2f(0.0f,1.0f);
            glVertex3f(fCentX-fTexW/2.0f,fCentY+fTexH/2.0f,0.0f);
            // Vertex 2
            glTexCoord2f(1.0f,0.0f);
            glVertex3f(fCentX+fTexW/2.0f,fCentY-fTexH/2.0f,0.0f);
            // Vertex 3
            glTexCoord2f(1.0f,1.0f);
            glVertex3f(fCentX+fTexW/2.0f,fCentY+fTexH/2.0f,0.0f);
        glEnd();
        
        pImage->disableTexture();

        SDL_GL_SwapBuffers( );
    }
    
    return true;
}

bool
MyContext::renderRect( float x, float y, float w, float h ) const
{
    glBegin(GL_TRIANGLE_STRIP);
        // Vertex 0
        glTexCoord2f(0.0f,0.0f);
        glVertex3f(x,y,0.0f);
        // Vertex 1
        glTexCoord2f(0.0f,1.0f);
        glVertex3f(x,y+h,0.0f);
        // Vertex 2
        glTexCoord2f(1.0f,0.0f);
        glVertex3f(x+w,y,0.0f);
        // Vertex 3
        glTexCoord2f(1.0f,1.0f);
        glVertex3f(x+w,y+h,0.0f);
    glEnd();  

    return true;
}

bool 
MyContext::renderCylinder(float fRenderSize[3], float fRenderPos[3], float fRotate[4], unsigned int uiType)
{
    glPushMatrix();
    glLoadIdentity();
    
    MyImage * pTop =  &_3dTex[uiType][INST_TOP];
    MyImage * pSide = &_3dTex[uiType][INST_SIDE]; 
    pTop->bindTexture();
    pTop->enableTexture();
    
    // Transformations
    glTranslatef(fRenderPos[0], fRenderPos[1], fRenderPos[2]);
    glRotatef(fRotate[0], fRotate[1], fRotate[2], fRotate[3]);
    glScalef(fRenderSize[0], fRenderSize[1], fRenderSize[2]);

    // Draw the top face
    glColor3f(0.0f, 1.0f, 0.0f);
    renderCircle(0.0f, 0.0f, -0.5f, 1.0f, 0.0f, 30, 0.0f);
    pTop->disableTexture();
    
    pSide->bindTexture();
    pSide->enableTexture();
    // Draw the connecting frame
    glColor3f(0.0f, 0.0f, 1.0f);
    renderCircle(0.0f, 0.0f, -0.5f, 1.0f, 1.0f, 50, 1.0f);
    
    pSide->disableTexture();

    
    // Draw the bottom plane
    pTop->bindTexture();
    pTop->enableTexture();
    
    glColor3f(1.0f, 0.0f, 0.0f);
    renderCircle(0.0f, 0.0f, 0.5f, 1.0f, 0.0f, 50, 0.0f);
    
    pTop->disableTexture();
    
    glPopMatrix();
    
    return true;
}


bool 
MyContext::renderCone(float fRenderSize[3], float fRenderPos[3], float fRotate[4], unsigned int uiType)
{
    glPushMatrix();
    glLoadIdentity();
    
    MyImage * pTop =  &_3dTex[uiType][INST_TOP]; 
    pTop->bindTexture();
    pTop->enableTexture();
    
    // Transformations
    glTranslatef(fRenderPos[0], fRenderPos[1], fRenderPos[2]);
    glRotatef(fRotate[0], fRotate[1], fRotate[2], fRotate[3]);
    glScalef(fRenderSize[0], fRenderSize[1], fRenderSize[2]);

    // Draw a cone
    glColor3f(1.0f, 0.0f, 0.0f);
    renderCircle(0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 50, 1.0f);
    
    // Draw the flat part beneath!
    glColor3f(0.0f, 0.0f, 1.0f);
//    renderCircle(0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 50);
    pTop->disableTexture();
    glPopMatrix();
    return true;
}


bool
MyContext::renderCircle(float fX, float fY, float fZ, float fRad, float fInRad, int iSides, float fZOffset)
{
    glBegin(GL_TRIANGLE_STRIP);
        for(int i=0; i<=iSides; i++)
        {
            /* Find and draw a vertex from the circle */
            float fTheta=(float)i*(2.0f*3.1415)/(float)iSides;
            // outer point
            glTexCoord2f((float)i/(float)(iSides), 0.0f);
            glVertex3f(fX + fRad*cos(fTheta), fY + fRad*sin(fTheta), fZ);
            // inner point
            glTexCoord2f((float)i/(float)(iSides), 1.0f);
            glVertex3f(fX + fInRad*cos(fTheta), fY + fInRad*sin(fTheta), fZ + fZOffset);
        }
        // last point
        glTexCoord2f(1.0f, 0.0f);
        float fTheta=(float)(iSides+1)*(2.0f*3.1415)/(float)iSides;
        glVertex3f(fX + fRad*cos(fTheta), fY + fRad*sin(fTheta), fZ);
    glEnd();
    return true;
}
